/**
* \file		ArbreTech.c
* \brief	Code des fonctions du module ArbreTech
* \details	C'est ici qu'est le code des accesseurs, mutateurs ainsi que
*		la fonction de test vérifant le bon fonctionnement du module
*		ArbreTech.
*		Une description de la structure ArbreTech est fournie à
*		la rubrique \link ArbreTech.h
*/

#include "ArbreTech.h"
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>

/*========================== Gestion de la mémoire ==========================*/

void initArbreTech(ArbreTech *pAT)
{
   setSARecolteArbreTech(pAT, NULL);
   setSAPopArbreTech(pAT, NULL);
   setSAMilitArbreTech(pAT, NULL);
}

void creerArbreTech(ArbreTech **ppAT)
{
   *ppAT = (ArbreTech*)malloc(sizeof(ArbreTech));
   initArbreTech(*ppAT);
}

void libereArbreTech(ArbreTech *pAT)
{
   SousArbre *pSAtemp;

   pSAtemp = getRecolteArbreTech(pAT);
   if(NULL != pSAtemp)
	{
	   detruireSousArbre(pSAtemp);
	}

   pSAtemp = getPopArbreTech(pAT);
   if(NULL != pSAtemp)
	{
	   detruireSousArbre(pSAtemp);
	}


   pSAtemp = getMilitArbreTech(pAT);
   if(NULL != pSAtemp)
	{
	   detruireSousArbre(pSAtemp);
	}

}

void detruireArbreTech(ArbreTech *pAT)
{
   libereArbreTech(pAT);
   free(pAT);
}

/*========================== Création de l'arbre ==========================*/
void creerDepuisFichierArbreTech(ArbreTech **ppAT, char *fichierData)
{
   SousArbre * pSAInter;

   FILE* f;
   /* bricolage de l'adresse du fichier à partir de la racine */
   char adresse[100] = {"./data/"};
   strcat(adresse, fichierData);

   /* récupération des données du fichier */
   f = fopen(adresse, "r");
   if(f == NULL)
	{
	   printf("Erreur lors de l'ouverture du fichier de données des terrains.\n");
	   assert(f);
	}

   creerArbreTech(ppAT);


   pSAInter = getPopArbreTech(*ppAT);
   creerDepuisFichierSousArbre(&pSAInter,f);
   setSARecolteArbreTech(*ppAT, pSAInter);

   pSAInter = getPopArbreTech(*ppAT);
   creerDepuisFichierSousArbre(&pSAInter,f);
   setSAPopArbreTech(*ppAT, pSAInter);

   pSAInter = getMilitArbreTech(*ppAT);
   creerDepuisFichierSousArbre(&pSAInter,f);
   setSAMilitArbreTech(*ppAT, pSAInter);


   fclose(f);

}

void finitionsArbreTech(ArbreTech *pAT)
{
   int i, j, nbDebl, nbBr, IDTemp;
   Technologie *ptechTraitee, *ptechTemp;
   SousArbre *pSA = NULL;

/* Finitions du sous-arbre des Récoltes */
   pSA = getRecolteArbreTech(pAT);
   nbBr = getnbBranchesSousArbre(pSA);

   for(i=0; i<nbBr; i++)
	{

	   ptechTraitee = getDebBrancheSousArbre(pSA, i);
	   while(ptechTraitee != NULL)
		{
           nbDebl = getNbTechDebloqueesTech(ptechTraitee);

           for(j=0; j<nbDebl ; j++)
           {
               IDTemp = getIemeIDTechDebloqueeTech(ptechTraitee, j);
               ptechTemp = getTechDepIDArbreTech(pAT, IDTemp);
               setTabTechDebloqueesTech(ptechTraitee, ptechTemp, j);
           }

		   ptechTraitee = getTechSuivTech(ptechTraitee);
		}
	}


/* Finitions du sous-arbre des Populations */
   pSA = getPopArbreTech(pAT);
   nbBr = getnbBranchesSousArbre(pSA);

   for(i=0; i<nbBr; i++)
	{
	   ptechTraitee = getDebBrancheSousArbre(pSA, i);

	   while(ptechTraitee != NULL)
		{
           nbDebl = getNbTechDebloqueesTech(ptechTraitee);

           for(j=0; j<nbDebl ; j++)
           {
               IDTemp = getIemeIDTechDebloqueeTech(ptechTraitee, j);
               ptechTemp = getTechDepIDArbreTech(pAT, IDTemp);
               setTabTechDebloqueesTech(ptechTraitee, ptechTemp, j);
           }

		   ptechTraitee = getTechSuivTech(ptechTraitee);
		}
	}

/* Finitions du sous-arbre des Récoltes */
   pSA = getMilitArbreTech(pAT);
   nbBr = getnbBranchesSousArbre(pSA);

   for(i=0; i<nbBr; i++)
	{
	   ptechTraitee = getDebBrancheSousArbre(pSA, i);

	   while(ptechTraitee != NULL)
		{
		   nbDebl = getNbTechDebloqueesTech(ptechTraitee);

	   for(j=0; j<nbDebl ; j++)
		{
		   IDTemp = getIemeIDTechDebloqueeTech(ptechTraitee, j);
		   ptechTemp = getTechDepIDArbreTech(pAT, IDTemp);
		   setTabTechDebloqueesTech(ptechTraitee, ptechTemp, j);
		}

		   ptechTraitee = getTechSuivTech(ptechTraitee);
		}
	}
}

/*============================= Accesseurs =============================*/

SousArbre *getRecolteArbreTech(const ArbreTech *pAT)
{
   return pAT->pRecolte;
}

SousArbre *getPopArbreTech(const ArbreTech *pAT)
{
   return pAT->pPop;
}

SousArbre *getMilitArbreTech(const ArbreTech *pAT)
{
   return pAT->pMilit;
}

Technologie *getTechDepIDArbreTech(const ArbreTech *pAT, int ID)
{
   Technologie *ptech;
   SousArbre *pSA;
   int numSA = getNumSADepuisIDTech(ID);


   if(numSA == 0)
	{
	   pSA = pAT->pRecolte;
	}
    else
	{
	   if(numSA == 1)
		{
		   pSA = pAT->pPop;
		}
	   else
		{
		   if(numSA == 2)
			{
			   pSA = pAT->pMilit;
			}
		   else
			{
			   printf("ID invalide \n");
			}
		}
	}

   ptech = getTechSousArbre(pSA, ID);
   return ptech;
}

/*================= Accéder aux données d'une technologie =================*/

char *getNomDepIDArbreTech(const ArbreTech *pAT, int ID)
{
   return getNomTech(getTechDepIDArbreTech(pAT, ID));
}

char *getDescriptionDepIDArbreTech(const ArbreTech *pAT, int ID)
{
   return getDescriptionTech(getTechDepIDArbreTech(pAT, ID));
}

int getCoutBoisDepIDArbreTech(const ArbreTech *pAT, int ID)
{
   return getCoutBoisTech(getTechDepIDArbreTech(pAT, ID));
}

int getCoutMetalDepIDArbreTech(const ArbreTech *pAT, int ID)
{
   return getCoutMetalTech(getTechDepIDArbreTech(pAT, ID));
}

int getCoutBiereDepIDArbreTech(const ArbreTech *pAT, int ID)
{
   return getCoutBiereTech(getTechDepIDArbreTech(pAT, ID));
}

int getCoutNourritureDepIDArbreTech(const ArbreTech *pAT, int ID)
{
   return getCoutNourritureTech(getTechDepIDArbreTech(pAT, ID));
}

int getBonusAttaqueDepIDArbreTech(const ArbreTech *pAT, int ID)
{
   return getBonusAttaqueTech(getTechDepIDArbreTech(pAT, ID));
}

int getBonusDefenseDepIDArbreTech(const ArbreTech *pAT, int ID)
{
   return getBonusDefenseTech(getTechDepIDArbreTech(pAT, ID));
}

int getBonusFeconditeDepIDArbreTech(const ArbreTech *pAT, int ID)
{
   return getBonusFeconditeTech(getTechDepIDArbreTech(pAT, ID));
}

int getBonusMortaliteDepIDArbreTech(const ArbreTech *pAT, int ID)
{
   return getBonusMortaliteTech(getTechDepIDArbreTech(pAT, ID));
}

int getBonusImmigrationDepIDArbreTech(const ArbreTech *pAT, int ID)
{
   return getBonusImmigrationTech(getTechDepIDArbreTech(pAT, ID));
}

int getBonusEmigrationDepIDArbreTech(const ArbreTech *pAT, int ID)
{
   return getBonusEmigrationTech(getTechDepIDArbreTech(pAT, ID));
}

int getBonusMoralDepIDArbreTech(const ArbreTech *pAT, int ID)
{
   return getBonusMoralTech(getTechDepIDArbreTech(pAT, ID));
}

int getBonusProdDepIDArbreTech(const ArbreTech *pAT, int ID)
{
   return getBonusProdTech(getTechDepIDArbreTech(pAT, ID));
}

int getMalusAttaqueDepIDArbreTech(const ArbreTech *pAT, int ID)
{
   return getMalusAttaqueTech(getTechDepIDArbreTech(pAT, ID));
}

int getMalusDefenseDepIDArbreTech(const ArbreTech *pAT, int ID)
{
   return getMalusDefenseTech(getTechDepIDArbreTech(pAT, ID));
}

int getMalusFeconditeDepIDArbreTech(const ArbreTech *pAT, int ID)
{
   return getMalusFeconditeTech(getTechDepIDArbreTech(pAT, ID));
}

int getMalusMortaliteDepIDArbreTech(const ArbreTech *pAT, int ID)
{
   return getMalusMortaliteTech(getTechDepIDArbreTech(pAT, ID));
}

int getMalusImmigrationDepIDArbreTech(const ArbreTech *pAT, int ID)
{
   return getMalusImmigrationTech(getTechDepIDArbreTech(pAT, ID));
}

int getMalusEmigrationDepIDArbreTech(const ArbreTech *pAT, int ID)
{
   return getMalusEmigrationTech(getTechDepIDArbreTech(pAT, ID));
}

int getMalusMoralDepIDArbreTech(const ArbreTech *pAT, int ID)
{
   return getMalusMoralTech(getTechDepIDArbreTech(pAT, ID));
}

int getMalusProdDepIDArbreTech(const ArbreTech *pAT, int ID)
{
   return getMalusProdTech(getTechDepIDArbreTech(pAT, ID));
}

/*============================= Mutateurs =============================*/

void setSARecolteArbreTech(ArbreTech *pAT, SousArbre *pSA)
{
   pAT->pRecolte = pSA;
}

void setSAPopArbreTech(ArbreTech *pAT, SousArbre *pSA)
{
   pAT->pPop = pSA;
}

void setSAMilitArbreTech(ArbreTech *pAT, SousArbre *pSA)
{
   pAT->pMilit = pSA;
}

/*========================== Fonctions autres ==========================*/
void devTechArbreTech(ArbreTech *pAT, int IDTech, int modificateurs[8])
{
   int i, nbTechDeb;
   int modificateur = 0;
   Technologie *ptech, *ptechBis;


   /* Edition du champ dev pour la technologie développée */
   ptech = getTechDepIDArbreTech(pAT, IDTech);
   setDevTech(ptech, 1);

   /* Edition du champ Prerequis pour les technologies qui la nécessitent */
   nbTechDeb = getNbTechDebloqueesTech(ptech);

   for(i=0; i<nbTechDeb; i++)
	{
	   ptechBis = getIemeTechDebloqueeTech(ptech, i);
	   setDevTech(ptechBis, 1);
	}

   /*Edition des champs de la population et de l'entrepot en fonction des bonus apportés*/


 modificateurs[2] = modificateur = getBonusFeconditeTech(ptech) - getMalusFeconditeTech(ptech);
 
 modificateurs[3] = getBonusMortaliteTech(ptech) - getMalusMortaliteTech(ptech);
 
 modificateurs[4] = getBonusImmigrationTech(ptech) - getMalusImmigrationTech(ptech);

 modificateurs[5] = getBonusEmigrationTech(ptech) - getMalusEmigrationTech(ptech);

 modificateurs[6] = getBonusMoralTech(ptech) - getMalusMoralTech(ptech);

 modificateurs[7] = getBonusProdTech(ptech) - getMalusProdTech(ptech);


}

/*=========================== Fonctions de Test ===========================*/

void testArbreTech()
{
   ArbreTech *pAT = NULL;
   char *fichierDat = {"DatTech"};
   Technologie *ptech, *ptechBis;

   int i, nbTechDeb;
   int modificateurs[8] = {0,0,0,0,0,0,0,0};

   /* Test des get pour Technologie à partir d'ID */
/*   int (*tabpGet[])(const ArbreTech *, int) = {
	getCoutBoisDepIDArbreTech,
	getCoutMetalDepIDArbreTech,
	getCoutBiereDepIDArbreTech,
	getCoutNourritureDepIDArbreTech,
	getBonusAttaqueDepIDArbreTech,
	getBonusDefenseDepIDArbreTech,
	getBonusFeconditeDepIDArbreTech,
	getBonusMortaliteDepIDArbreTech,
	getBonusImmigrationDepIDArbreTech,
	getBonusEmigrationDepIDArbreTech,
	getBonusMoralDepIDArbreTech,
	getBonusProdDepIDArbreTech,
	getMalusAttaqueDepIDArbreTech,
	getMalusDefenseDepIDArbreTech,
	getMalusFeconditeDepIDArbreTech,
	getMalusMortaliteDepIDArbreTech,
	getMalusImmigrationDepIDArbreTech,
	getMalusEmigrationDepIDArbreTech,
	getMalusMoralDepIDArbreTech,
	getMalusProdDepIDArbreTech
	};
*/
   SousArbre *pSA;

   printf("\nTest de l'Arbre des Technologies\n");

   printf("\tCréation de l'Arbre à partir du fichier de données\t");
   creerDepuisFichierArbreTech(&pAT, fichierDat);
   finitionsArbreTech(pAT);
   printf("OK\n");

   printf("\tContrôle de l'accessibilité des champs des Technologies\t");
   pSA = getRecolteArbreTech(pAT);
   testTousChampsTechAccessibles(pSA);

/*   printf("\n");
   affSousArbre(pSA);
*/
   pSA = getPopArbreTech(pAT);
   testTousChampsTechAccessibles(pSA);

/*   affSousArbre(pSA);
*/
   pSA = getMilitArbreTech(pAT);
   testTousChampsTechAccessibles(pSA);
/*   affSousArbre(pSA);
*/
   printf("OK\n");

   printf("\tDéveloppement de technologie\t\t\t\t");
   devTechArbreTech(pAT, 100000, modificateurs);

   ptech = getTechDepIDArbreTech(pAT, 100000);

   nbTechDeb = getNbTechDebloqueesTech(ptech);
   assert(1 == getDevTech(ptech));

   for(i=0; i<nbTechDeb; i++)
	{
	   ptechBis = getIemeTechDebloqueeTech(ptech, i);
	   assert(1 == getDevTech(ptechBis));
	}
   printf("OK\n\n");

/*
   ptech = getTechDepIDArbreTech(pAT, 120000);
   printf("Nom : %s\n", getNomTech(ptech));
   printf("Nom Test2 : %s\n", getNomDepIDArbreTech(pAT, 100000));

   printf("La Technologie a pour nom : %s\n", getNomDepIDArbreTech(pAT, 110000));
   printf("La Technologie a pour description : %s\n", getDescriptionDepIDArbreTech(pAT, 110000));
   for(i=0; i<20; i++)
	{
	   printf("la valeur est : %d\n", tabpGet[i](pAT, 110000));
	}
*/
   detruireArbreTech(pAT);
}

